#ifndef MATRIX_FUNC_OBJ
#define MATRIX_FUNC_OBJ

#include <iostream>

using namespace std;

// function objects for various apply() operations:

/** function object for operator =, it takes two arguments, a is the lvalue and c is the rvalue **/
template<class T> struct Assign {
    void operator()(T& a, const T& c) { a = c; }
};

/** function object for operator +, it takes two arguments, a is the lvalue and c is the rvalue **/
template<class T> struct Add_assign {
    void operator()(T& a, const T& c) { a += c; }
};

/** function object for operator *, it takes two arguments, a is the lvalue and c is the rvalue **/
template<class T> struct Mul_assign {
    void operator()(T& a, const T& c) { a *= c; }
};

/** function object for operator -, it takes two arguments, a is the lvalue and c is the rvalue **/
template<class T> struct Minus_assign {
    void operator()(T& a, const T& c) { a -= c; }
};

/** function object for operator =/, it takes two arguments, a is the lvalue and c is the rvalue **/
template<class T> struct Div_assign {
    void operator()(T& a, const T& c) { a /= c; }
};

/** function object for operator %, it takes two arguments, a is the lvalue and c is the rvalue **/
template<class T> struct Mod_assign {
    void operator()(T& a, const T& c) { a %= c; }
};

/** function object for operator |, it takes two arguments, a is the lvalue and c is the rvalue **/
template<class T> struct Or_assign {
    void operator()(T& a, const T& c) { a |= c; }
};

/** function object for operator ^, it takes two arguments, a is the lvalue and c is the rvalue **/
template<class T> struct Xor_assign {
    void operator()(T& a, const T& c) { a ^= c; }
};

/** function object for operator &, it takes two arguments, a is the lvalue and c is the rvalue **/
template<class T> struct And_assign {
    void operator()(T& a, const T& c) { a &= c; }
};

/** function object for operator !, it takes one arguments, a is both the lvalue and the rvalue **/
template<class T> struct Not_assign {
    void operator()(T& a) { a = !a; }
};

/** function object for operator !, it takes one arguments, a is the rvalue **/
template<class T> struct Not {
    T operator()(T& a) { return !a; }
};

/** function object for operator -, it takes one arguments, a is the rvalue **/
template<class T> struct Unary_minus {
    T operator()(T& a) { return -a; }
};

/** function object for operator ~, it takes one arguments, a is the rvalue **/
template<class T> struct Complement {
    T operator()(T& a) { return ~a; }
};

#endif
